package com.grm.sys.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.grm.common.exception.BusinessException;
import com.grm.common.utils.*;
import com.grm.sys.constant.SysUserConstant;
import com.grm.sys.mapper.*;
import com.grm.sys.model.*;
import com.grm.sys.request.user.ChangePasswordParam;
import com.grm.sys.request.user.SysUserAddParam;
import com.grm.sys.request.user.SysUserQueryParam;
import com.grm.sys.request.user.SysUserUpdateParam;
import com.grm.sys.response.SysDeptResponse;
import com.grm.sys.response.SysUserResponse;
import com.grm.sys.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysPostMapper sysPostMapper;
    @Autowired
    private SysPermMapper sysPermMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public PageInfo<SysUserResponse> querySelective(Integer pageNum, Integer pageSize, SysUserQueryParam queryParam) {
        List<SysUser> sysUserList;
        if (ObjectUtils.isNotEmpty(queryParam.getDeptId())) {
            // 查询所有子部门
            List<SysDept> childDeptList = sysDeptMapper.queryAllChildren(Collections.singletonList(queryParam.getDeptId()));
            List<Long> childDeptIds = childDeptList.stream().map(SysDept::getId).toList();

            PageHelper.startPage(pageNum, pageSize);
            sysUserList = sysUserMapper.querySelective(queryParam, childDeptIds);
        } else {
            PageHelper.startPage(pageNum, pageSize);
            sysUserList = sysUserMapper.querySelective(queryParam, null);
        }
        List<SysUserResponse> sysUserRespList = sysUserList.stream()
                .map(this::setUserInfo)
                .collect(Collectors.toList());
        return new PageInfo<>(sysUserRespList);
    }

    @Override
    public SysUserResponse queryById(Long userId) {
        SysUser sysUser = sysUserMapper.queryById(userId);
        return setUserInfo(sysUser);
    }

    private SysUserResponse setUserInfo(SysUser sysUser) {
        SysUserResponse sysUserResponse = new SysUserResponse();
        BeanUtils.copyProperties(sysUser, sysUserResponse);

        setDeptInfo(sysUser, sysUserResponse);
        setPostInfo(sysUser, sysUserResponse);
        setRoleInfo(sysUser, sysUserResponse);

        return sysUserResponse;
    }

    // 设置部门信息
    private void setDeptInfo(SysUser sysUser, SysUserResponse sysUserResponse) {
        if (ObjectUtils.isNotEmpty(sysUser.getDeptId())) {
            List<SysDept> sysDeptList = sysDeptMapper.queryParentDeptList(sysUser.getDeptId());
            List<SysDeptResponse> sysDeptResponses = ListBeanUtils.copyListProperties(sysDeptList, SysDeptResponse::new);
            sysUserResponse.setSysDeptTree(TreeUtils.getTree(sysDeptResponses));

            SysDept sysDept = sysDeptMapper.queryById(sysUser.getDeptId());
            sysUserResponse.setSysDept(sysDept);
        }
    }

    // 设置岗位信息
    private void setPostInfo(SysUser sysUser, SysUserResponse sysUserResponse) {
        if (ObjectUtils.isNotEmpty(sysUser.getPostId())) {
            SysPost sysPost = sysPostMapper.queryById(sysUser.getPostId());
            sysUserResponse.setSysPost(sysPost);
        }
    }

    // 设置角色信息
    private void setRoleInfo(SysUser sysUser, SysUserResponse sysUserResponse) {
        List<Long> roleIds = sysUserRoleMapper.queryRoleIds(sysUser.getId());
        if (ObjectUtils.isNotEmpty(roleIds)) {
            List<SysRole> sysRoles = sysRoleMapper.queryByIds(roleIds);
            sysUserResponse.setSysRoles(sysRoles);
        }
    }


    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void changePassword(ChangePasswordParam changePasswordParam) {
        Long loginId = jwtUtil.getUserId();
        SysUser dbSysUser = sysUserMapper.queryById(loginId);
        if (!PasswordUtils.checkPassword(changePasswordParam.getOldPassword(), dbSysUser.getPassword())) {
            throw new BusinessException(500, "输入的旧密码错误！");
        }
        if (!changePasswordParam.getNewPassword().equals(changePasswordParam.getRePassword())) {
            throw new BusinessException(500, "两次输入的密码不一致！");
        }
        // 修改密码
        sysUserMapper.updatePassword(loginId, PasswordUtils.encryptPassword(changePasswordParam.getNewPassword()));
    }

    /*
    propagation = Propagation.REQUIRED: 如果当前存在事务，则加入该事务，如果不存在事务，则创建一个新的事务。
    isolation = Isolation.READ_COMMITTED: 事务隔离级别为读已提交，即事务只能读取已经提交的数据。
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void add(SysUserAddParam sysUserAddParam) {
        SysUser dbSysUser = sysUserMapper.queryByUsername(sysUserAddParam.getUsername());
        if (dbSysUser != null) {
            throw new BusinessException("用户已存在！");
        }
        // sysUserAddParam转换为sysUser 将参数对象与数据库实体对象分开可以降低它们之间的耦合度，使得业务逻辑更加清晰
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserAddParam, sysUser);
        sysUser.setPassword(PasswordUtils.encryptPassword(SysUserConstant.DEFAULT_PASSWORD));
        sysUserMapper.add(sysUser);

        // 添加角色关联
        List<Long> roleIds = sysUserAddParam.getRoleIds();
        if (ObjectUtils.isNotEmpty(roleIds)) {
            sysUserRoleMapper.batchInsert(sysUser.getId(), roleIds);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void update(SysUserUpdateParam sysUserUpdateParam) {
        SysUser dbSysUser = checkUserExistence(sysUserUpdateParam.getId());
        prohibitModificationForAdmin(sysUserUpdateParam.getId());
        checkUsernameAvailability(sysUserUpdateParam.getId(), sysUserUpdateParam.getUsername());

        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserUpdateParam, sysUser);
        // 不修改密码,防止绕过前台篡改
        sysUser.setPassword(dbSysUser.getPassword());
        sysUserMapper.update(sysUser);

        updateRoles(sysUser.getId(), sysUserUpdateParam.getRoleIds());
    }

    // 校验用户是否存在
    private SysUser checkUserExistence(Long userId) {
        SysUser dbSysUser = sysUserMapper.queryById(userId);
        if (dbSysUser == null) {
            throw new BusinessException("用户不存在！");
        }
        return dbSysUser;
    }

    // 校验用户是否是超级管理员
    private void prohibitModificationForAdmin(Long userId) {
        if (userId.equals(1L)) {
            throw new BusinessException("不允许修改系统管理员！");
        }
    }

    // 校验用户名唯一性
    private void checkUsernameAvailability(Long userId, String username) {
        SysUser dbSysUser = sysUserMapper.queryByUsername(username);
        if (dbSysUser != null && !userId.equals(dbSysUser.getId())) {
            throw new BusinessException("修改后的用户名已被别人使用！");
        }
    }

    // 更新用户角色关系
    private void updateRoles(Long userId, List<Long> newRoleIds) {
        List<Long> existingRoleIds = sysUserRoleMapper.queryRoleIds(userId);

        List<Long> rolesToRemove = new ArrayList<>(existingRoleIds);
        rolesToRemove.removeAll(newRoleIds);
        if (!rolesToRemove.isEmpty()) {
            sysUserRoleMapper.deleteByUserIdAndRoleIds(userId, rolesToRemove);
        }

        List<Long> rolesToAdd = new ArrayList<>(newRoleIds);
        rolesToAdd.removeAll(existingRoleIds);
        if (ObjectUtils.isNotEmpty(rolesToAdd)) {
            sysUserRoleMapper.batchInsert(userId, rolesToAdd);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void delete(List<Long> userIds) {
        if (ObjectUtils.isNotEmpty(userIds)) {
            if (userIds.contains(1L)) {
                throw new BusinessException("不能删除系统管理员！");
            }
            // 删除用户
            sysUserMapper.deleteByIds(userIds);
            // 删除用户-角色管理
            sysUserRoleMapper.deleteByUserIds(userIds);
        }
    }

    @Override
    public void resetPassword(Long userId) {
        sysUserMapper.updatePassword(userId, PasswordUtils.encryptPassword(SysUserConstant.DEFAULT_PASSWORD));
    }

    @Override
    public List<SysUserResponse> queryAll() {
        List<SysUser> sysUserList = sysUserMapper.queryAll();
        return sysUserList.stream()
                .map(this::setUserInfo)
                .collect(Collectors.toList());
    }
}
